/*
 * Treatment Record Info
 */
/*
 * TreatmentRecordInfo.java
 * 
 * @version 1.0, March 15, 2011
 * CS 2340 Team 10: Cyberdyne Systems
 */
package edu.gatech.oad.cyberdoc.domain;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.json.JSONException;
import org.json.JSONObject;

/**
 * A class storing all of the information about a TreatmentRecord.
 * 
 * @author John Girata
 * @version 1.0, March 15, 2011
 */
public class TreatmentRecordInfo implements JSONSerializable {

	/**
	 * The logger for this class.
	 */
	private static final Logger LOG;

	/**
	 * The list of legal fields.
	 */
	public static final List<String> KEYS;

	/**
	 * The items a TreatmentRecord "knows".
	 */
	private final Map<String, Object> fields;

	static {
		LOG = Logger.getLogger("edu.gatech.oad.cyberdoc.domain."
				+ "TreatmentRecordInfo");

		KEYS = new ArrayList<String>();
		KEYS.add("doctor");
		KEYS.add("nurse");
		KEYS.add("patient");
		KEYS.add("date");
		KEYS.add("doctorOrders");
		KEYS.add("symptom");
		KEYS.add("vitalSigns");
		KEYS.add("diagnosis");
	}

	/**
	 * Creates a new TreatmentRecordInfo by first making a copy of the fields in
	 * old (if not null), then updating those values with the values in map (if
	 * not null).
	 * 
	 * @param old
	 *            The default values
	 * @param map
	 *            The new values
	 */
	public TreatmentRecordInfo(TreatmentRecordInfo old, Map<String, Object> map) {
		if (old == null) {
			old = new DefaultTreatmentRecordInfo();
		}

		fields = old.getShallowFieldsCopy();

		if (map != null) {
			for (Map.Entry<String, Object> entry : map.entrySet()) {
				fields.put(entry.getKey(), entry.getValue());
			}
		}
	}

	/**
	 * Creates an instance of this class from a JSONObject, as required by
	 * DatabaseSerializable.
	 * 
	 * @param object
	 *            The information from the database to use to create this User
	 */
	@SuppressWarnings("rawtypes")
	public TreatmentRecordInfo(JSONObject object) {
		fields = new HashMap<String, Object>();

		try {
			for (final Iterator iterator = object.keys(); iterator.hasNext();) {
				String key = iterator.next().toString();
				// FIXME Some values may not be strings
				fields.put(key, object.getString(key));
			}
		} catch (JSONException e) {
			LOG.log(Level.SEVERE, "Unexpected exception", e);
		}
	}

	/**
	 * Creates a default TreatmentRecordInfo with all fields set to null.
	 */
	protected TreatmentRecordInfo() {
		fields = new HashMap<String, Object>();
	}

	/**
	 * Returns a field from this TreatmentRecordInfo, if it is a legal
	 * TreatmentRecordInfo field. Otherwise, an exception is thrown.
	 * 
	 * @param key
	 *            The field name
	 * @return The field's value
	 * @throws NoSuchElementException
	 *             If the field name is not a legal name
	 */
	protected Object getField(String key) throws NoSuchElementException {
		if (!KEYS.contains(key)) {
			throw new NoSuchElementException("The element " + key
					+ " does not exist.");
		}

		return fields.get(key);
	}

	/**
	 * Returns a shallow copy of the Map object mapping this
	 * TreatmentRecordInfo's fields to its values.
	 * 
	 * @return A shallow copy of this object's fields
	 */
	protected Map<String, Object> getShallowFieldsCopy() {
		final Map<String, Object> copy = new HashMap<String, Object>();

		for (String key : KEYS) {
			copy.put(key, fields.get(key));
		}

		return copy;
	}

	/**
	 * Returns a string representation of this TreatmentRecordInfo.
	 * 
	 * @return This object as a string
	 */
	public String toString() {
		final StringBuffer buffer = new StringBuffer();
		buffer.append('[');

		for (Map.Entry<String, Object> entry : fields.entrySet()) {
			buffer.append(entry.getKey() + "=" + entry.getValue() + ",");
		}

		buffer.delete(buffer.length() - 1, buffer.length());
		buffer.append(']');
		return buffer.toString();
	}

	/**
	 * Returns this TreatmentRecordInfo object encoded in a JSONObject.
	 * 
	 * @return This object as a JSONObject
	 */
	public JSONObject toJSONObject() {
		final JSONObject object = new JSONObject();

		for (Map.Entry<String, Object> entry : fields.entrySet()) {
			Object value = "";

			if (entry.getValue() != null) {
				if (entry.getValue() instanceof JSONSerializable) {
					value = ((JSONSerializable) entry.getValue())
							.toJSONObject();
				} else {
					value = entry.getValue().toString();
				}
			}

			try {
				object.put(entry.getKey(), value);
			} catch (JSONException e) {
				LOG.log(Level.SEVERE, "Unexpected exception.", e);
			}
		}

		return object;
	}
}
